﻿using UnityEngine;

namespace HotPlayer.Physic2D
{
    public class Polygon2D : Shape2D
    {
        protected Vector2[] _pointsOS;
        public Vector2[] pointsOS
        {
            get => _pointsOS;
            set
            {
                _pointsOS = value;
                UpdatePointsWS();
            }
        }

        public int pointCount => pointsOS.Length;

        public void Update(Vector2[] points, Matrix4x4 matrix)
        {
            _pointsOS = points;
            local2worldMatrix.Update(matrix);
            UpdatePointsWS();
        }
        
        public Vector2[] pointsWS { get; protected set; }

        protected override void UpdatePointsWS()
        {
            if (pointsWS == null || pointsWS.Length != pointsOS.Length)
            {
                pointsWS = new Vector2[pointsOS.Length];
            }
            for (var i = 0; i < _pointsOS.Length; i++)
            {
                pointsWS[i] = local2worldMatrix.MultiplyPoint(_pointsOS[i]);
            }
        }
        
        public override Vector2 GetFarthestPointInDirection(Vector2 direction)
        {
            //投影越大越远
            var index = 0;
            var bestProjection = Vector2.Dot(pointsWS[0], direction);
            for (int i = 1; i < pointsWS.Length; i++)
            {
                var projection = Vector2.Dot(pointsWS[i], direction);
                if (projection > bestProjection)
                {
                    index = i;
                    bestProjection = projection;
                }
            }
            return pointsWS[index];
        }
        
        public Vector2 GetNearestPointInDirection(Vector2 direction)
        {
            //投影越大越远
            var index = 0;
            var bestProjection = Vector2.Dot(pointsWS[0], direction);
            for (int i = 1; i < pointsWS.Length; i++)
            {
                var projection = Vector2.Dot(pointsWS[i], direction);
                if (projection < bestProjection)
                {
                    index = i;
                    bestProjection = projection;
                }
            }
            return pointsWS[index];
        }
        
        public Vector2 Support(Vector2 direction)
        {
            return GetFarthestPointInDirection(direction);
        }

        public override Vector2 AveragePoint()
        {
            var avg = Vector2.zero;
            for (int i = 0; i < pointsWS.Length; i++) {
                avg.x += pointsWS[i].x;
                avg.y += pointsWS[i].y;
            }
            avg.x /= pointsWS.Length;
            avg.y /= pointsWS.Length;
            return avg;
        }
    }
}